Skip to content

Support deleting users and groups via authctl#1372

Open
shiv-tyagi wants to merge 5 commits intocanonical:mainfrom
shiv-tyagi:authctl-delete
Open

Support deleting users and groups via authctl#1372
shiv-tyagi wants to merge 5 commits intocanonical:mainfrom
shiv-tyagi:authctl-delete

Conversation

@shiv-tyagi
Copy link
Copy Markdown
Contributor

Closes #640

This adds subcommands to authctl to allow deleting a user/group using CLI.

This also contains relevant tests to verify the functionality.

@shiv-tyagi shiv-tyagi force-pushed the authctl-delete branch 4 times, most recently from 935182f to 2922411 Compare March 29, 2026 17:48
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 29, 2026

Codecov Report

❌ Patch coverage is 80.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 80.00%. Comparing base (d5d6f6f) to head (05ddf87).
⚠️ Report is 8 commits behind head on main.

Files with missing lines Patch % Lines
authd-oidc-brokers/internal/broker/broker.go 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1372      +/-   ##
==========================================
- Coverage   80.02%   80.00%   -0.03%     
==========================================
  Files          20       20              
  Lines         991      990       -1     
==========================================
- Hits          793      792       -1     
  Misses        198      198              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@shiv-tyagi
Copy link
Copy Markdown
Contributor Author

shiv-tyagi commented Mar 29, 2026

image

Not sure why it is showing such a less coverage in cmd/authctl/* files. I have added quite some cases which should hit those lines. Please let me know if I am missing something. Thanks!

Edit: I think the reason is that those tests are building authctl and then running it using exec.Command(..) to test stuff... and not directly calling the go code in tests. But that way of testing is pre existing and I am following the same.

@shiv-tyagi shiv-tyagi marked this pull request as ready for review March 29, 2026 18:25
@nooreldeenmansour
Copy link
Copy Markdown
Member

Thanks for the PR!

Note that #640 has a sub-issue (#830) around cleaning up broker-stored user data on deletion. Since it's related, it would be good to address it in the same PR.

Copy link
Copy Markdown
Member

@nooreldeenmansour nooreldeenmansour left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! I did some experimentation and found a few issues worth addressing:

1. Home directory cleanup on user deletion

When a user is deleted, their home directory is left behind. We should either add a -r/--remove flag (similar to userdel ) to optionally clean it up, or at minimum make the warning message explicit that the home directory is preserved and requires manual cleanup.

2. Deleting a user's primary group should be blocked

We shouldn't allow deletion of a group that is the primary group of an existing user. This mirrors groupdel's behavior:

You may not remove the primary group of any existing user. You must remove the user before you remove the group.

It breaks the user's next login with: failed to update user "<username>": another system user exists with "<username>" name.

3. Deleting a user orphans their primary group

When a user is deleted, their primary group isn't cleaned up, leaving the database in an inconsistent state.

=== users query ===
<username>|10001|10001|<name>|/home/<username>

=== groups query ===
10000|<username>

The user can re-login, but is assigned a different GID 10001 (non-existent), while GID 10000 is orphaned. This also causes errors in id and groups:

<username>@authd-dev:~$ id
id: cannot find name for group ID 10001
uid=10001(<username>) gid=10001(10001) groups=10001(10001),24(cdrom),10000(<username>)

<username>@authd-dev:~$ groups
groups: cannot find name for group ID 10001
10001 cdrom <username>

4. Re-login after deletion assigns a new UID, breaking home directory ownership

If a deleted user logs back in and gets the same home directory, there is a chance they receive a different UID, meaning they will no longer own their home directory. checkHomeDirOwner detects UID/GID mismatch but only logs a warning in the jounal

@shiv-tyagi
Copy link
Copy Markdown
Contributor Author

shiv-tyagi commented Mar 30, 2026

Thanks for taking a look @nooreldeenmansour.

I will work on closing #830 as well in the same PR.

Regarding the issues you have highlighted,

When a user is deleted, their home directory is left behind. We should either add a -r/--remove flag (similar to userdel ) to optionally clean it up

Adding a flag to optionally delete the home directory makes sense.

We shouldn't allow deletion of a group that is the primary group of an existing user.

Makes sense. I will take care of this.

When a user is deleted, their primary group isn't cleaned up, leaving the database in an inconsistent state.

I intentionally did it that way because I was unsure about the scenarios where some other user is also manually made part of another users primary group. I would like to hear your thoughts on how do we handle this situation? Should we implement it in a way that the user's primary group deletion happens only when only that user was part of it's group?

Re-login after deletion assigns a new UID, breaking home directory ownership

This is similar to the warning we show with the delete command. Once a user is deleted, its UID can be assigned to another user. Similarly when it is recreated, it might get a new UID. I think we can add the wordings for later in the warning message. Other than that, I couldn't figure out an easy way to handle that. Our warning message already suggests to lock user instead of deleting to make sure the UID stays reserved. Anything else you have in mind to handle this?

@nooreldeenmansour
Copy link
Copy Markdown
Member

I would like to hear your thoughts on how do we handle this situation? Should we implement it in a way that the user's primary group deletion happens only when only that user was part of it's group?

I think it makes sense to handle this the standard UNIX way. As detailed in the userdel:

If USERGROUPS_ENAB is defined to yes in /etc/login.defs, userdel will delete the group with the same name as the user. To avoid inconsistencies in the passwd and group databases, userdel will check that this group is not used as a primary group for another user.

USERGROUPS_ENAB (boolean)
If set to yes, userdel will remove the user's group if it contains no more members.

Other than that, I couldn't figure out an easy way to handle that. Our warning message already suggests to lock user instead of deleting to make sure the UID stays reserved. Anything else you have in mind to handle this?

The warning message is likely sufficient, since it clearly states the UID drift as a potential consequence. I'll wait on @adombeck's suggestion regarding this

@shiv-tyagi
Copy link
Copy Markdown
Contributor Author

I think it makes sense to handle this the standard UNIX way.

That sounds reasonable. For the scenario where a user's primary group has other members as well - as far as I understand, authd can only determine whether some other user belongs to a users primary group if the other user itself is managed by authd (please correct me if that’s not accurate).

Based on that, we could safely delete a user’s primary group when it has no other members, while also issuing a warning that any manually added users in that group would lose their group membership.

@nooreldeenmansour @adombeck WDYT?

P.S. I know you’re busy with the upcoming release, so feel free to respond whenever convenient.

@adombeck
Copy link
Copy Markdown
Contributor

adombeck commented Apr 1, 2026

Thank you, @shiv-tyagi, for the PR and thank you @nooreldeenmansour for the excellent review!

Note that #640 has a sub-issue (#830) around cleaning up broker-stored user data on deletion. Since it's related, it would be good to address it in the same PR.

I agree that we should handle the deletion of the broker's user data before merging this PR, because it would be confusing if we still kept user data after running authctl delete user. However, since it requires adding a new API method to the broker, I expect it to be a quite big change itself, so maybe for the sake of having smaller PRs, which we can merge more quickly, it would make sense to do that in a separate PR which we merge before this one.

I would like to hear your thoughts on how do we handle this situation? Should we implement it in a way that the user's primary group deletion happens only when only that user was part of it's group?

I think it makes sense to handle this the standard UNIX way. As detailed in the userdel:

If USERGROUPS_ENAB is defined to yes in /etc/login.defs, userdel will delete the group with the same name as the user. To avoid inconsistencies in the passwd and group databases, userdel will check that this group is not used as a primary group for another user.

USERGROUPS_ENAB (boolean)
If set to yes, userdel will remove the user's group if it contains no more members.

I agree that we should handle it the same way userdel does when usergroups are enabled, but regardless of the value of USERGROUPS_ENAB. I don't see a use case for disabling this behavior in authd (and if there was one, the place to add the setting would be /etc/authd/authd.yaml).

Other than that, I couldn't figure out an easy way to handle that. Our warning message already suggests to lock user instead of deleting to make sure the UID stays reserved. Anything else you have in mind to handle this?

The warning message is likely sufficient, since it clearly states the UID drift as a potential consequence. I'll wait on @adombeck's suggestion regarding this

I agree, a warning message explaining the issue with file ownership and suggesting to disable the user instead is the best we can do.

@adombeck
Copy link
Copy Markdown
Contributor

adombeck commented Apr 1, 2026

That sounds reasonable. For the scenario where a user's primary group has other members as well - as far as I understand, authd can only determine whether some other user belongs to a users primary group if the other user itself is managed by authd (please correct me if that’s not accurate).

We don't have to worry about that, because the primary groups only exist in the authd database, not /etc/group, so local users can't be added to those groups (related: #1374).

@shiv-tyagi
Copy link
Copy Markdown
Contributor Author

shiv-tyagi commented Apr 6, 2026

Hi @adombeck @nooreldeenmansour

When a user is deleted, their home directory is left behind. We should either add a -r/--remove flag (similar to userdel ) to optionally clean it up

I tried implementing this in authd's User service. I am getting error deleting the home directory. When I checked I found that the authd's service is configured in a way that it cannot touch stuff inside /home. Would it be okay to add /home to the list of paths the authd process is allowed to read write?

Edit: the process would also require CAP_DAC_OVERRIDE, I just checked.

@3v1n0
Copy link
Copy Markdown
Contributor

3v1n0 commented Apr 6, 2026

When a user is deleted, their home directory is left behind. We should either add a -r/--remove flag (similar to userdel ) to optionally clean it up, or at minimum make the warning message explicit that the home directory is preserved and requires manual cleanup.

Also note that when targeting ubuntu we should also ensure that deluser (as we try to do with adduser) policies are respected too.

@adombeck
Copy link
Copy Markdown
Contributor

adombeck commented Apr 6, 2026

When I checked I found that the authd's service is configured in a way that it cannot touch stuff inside /home. Would it be okay to add /home to the list of paths the authd process is allowed to read write?

Yeah, we'll haven to loosen the restrictions on the authd systemd service (see debian/authd.service.in). ReadWritePaths=-/home should work for directories below /home, but home directories could also be elsewhere. We could try allow-list other directories, but maybe we should just remove the filesystem restrictions we currently have, because they don't really provide an effective security boundary anyway. I'll create an issue where we can discuss that.

@adombeck
Copy link
Copy Markdown
Contributor

adombeck commented Apr 6, 2026

Yeah, we'll haven to loosen the restrictions on the authd systemd service (see debian/authd.service.in)

Actually, after taking a closer look, I don't see anything in our existing service definition which would prevent writing to /home. Which error do you see? Can you commit the changes so I can try to reproduce it?

@adombeck
Copy link
Copy Markdown
Contributor

adombeck commented Apr 6, 2026

Also note that when targeting ubuntu we should also ensure that deluser (as we try to do with adduser) policies are respected too.

Which policies are you referring to, @3v1n0?

@shiv-tyagi
Copy link
Copy Markdown
Contributor Author

shiv-tyagi commented Apr 7, 2026

@adombeck

I have pushed my changes. This includes the broker side changes as well (I need to organise the commits better).

Actually, after taking a closer look, I don't see anything in our existing service definition which would prevent writing to /home. Which error do you see? Can you commit the changes so I can try to reproduce it?

Screenshot from 2026-04-07 08-25-17 ^ this is the error on the current systemd unit definition.

I checked again, turned out that it is a missing CAP_DAC_OVERRIDE capability in the authd process.
(earlier I was under an impression that not adding /home to ReadWritePaths might have been preventing it, but it looks like just doing that is not enough and if we add the above mentioned capability to the process, later is not even needed.)

@adombeck
Copy link
Copy Markdown
Contributor

adombeck commented Apr 7, 2026

I checked again, turned out that it is a missing CAP_DAC_OVERRIDE capability in the authd process.

That makes sense. Then let's add CAP_DAC_OVERRIDE to the CapabilityBoundingSet and explain in the comment above why we need it.

@shiv-tyagi
Copy link
Copy Markdown
Contributor Author

shiv-tyagi commented Apr 8, 2026

Hey @adombeck! I have submitted #1421 which contains the broker side of changes for user data deletion as suggested by you.

This PR is also ready for another round of review. I have addressed the comments posted by @nooreldeenmansour. Please take a look and feel free to suggest improvements.

@shiv-tyagi shiv-tyagi force-pushed the authctl-delete branch 3 times, most recently from 36493f1 to 05ddf87 Compare April 8, 2026 20:14
Signed-off-by: Shiv Tyagi <shivtyagi3015@gmail.com>
Signed-off-by: Shiv Tyagi <shivtyagi3015@gmail.com>
…letion

Signed-off-by: Shiv Tyagi <shivtyagi3015@gmail.com>
Signed-off-by: Shiv Tyagi <shivtyagi3015@gmail.com>
Signed-off-by: Shiv Tyagi <shivtyagi3015@gmail.com>
@shiv-tyagi
Copy link
Copy Markdown
Contributor Author

TestUserDeleteCommand is failing because I have removed broker side changes from this PR to help with the review. I will rebase when #1421 is merged and they should pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support deletion of users and groups via authctl

4 participants